package com.github.cyf.upload.service.impl;

import com.github.cyf.common.util.DateUtil;
import com.github.cyf.common.util.RedisUtil;
import com.github.cyf.upload.constant.FileConstant;
import com.github.cyf.upload.entity.dto.FileUploadDTO;
import com.github.cyf.upload.local.pojo.LocalFileUploadResult;
import com.github.cyf.upload.local.pojo.UploadFileParam;
import com.github.cyf.upload.local.pojo.UploadProgress;
import com.github.cyf.upload.entity.po.FileInfo;
import com.github.cyf.upload.mpService.FileInfoService;
import com.github.cyf.upload.properties.UploadProperties;
import com.github.cyf.upload.service.FileService;
import com.github.cyf.upload.enums.SliceUploadStatus;
import com.github.cyf.upload.util.FileUtil;
import com.github.cyf.upload.local.LocalUpload;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * @author chenyifan
 * @create 2025-05-22 15:59
 */
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private UploadProperties uploadProperties;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private FileInfoService fileInfoService;

    @Override
    public FileUploadDTO sliceUpload(UploadFileParam param) {
        String savePath = getSavePath(param.getMd5(), param.getName());
        LocalFileUploadResult uploadResult = LocalUpload.sliceFileUploader(param, savePath, param.getChunkSize(), request);
        String relativePath = FileUtil.getRelativePath(uploadProperties.getSaveDir(), uploadResult.getFilePath());
        if (uploadResult.isUploadComplete()) { // 全部上传
            //把上传进度信息存进redis
            redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), Boolean.TRUE.toString());
            // 保存文件信息到数据库
            File file = new File(uploadResult.getFilePath());
            FileInfo fileInfo = FileInfo.builder()
                    .fileName(file.getName())
                    .filePath(relativePath)
                    .fileSize(file.length())
                    .md5(param.getMd5())
                    .fileType(FilenameUtils.getExtension(file.getName()))
                    .createTime(DateUtil.timestampToLocalDateTime(file.lastModified()))
                    .originalName(param.getName())
                    .build();
            fileInfoService.save(fileInfo);
        } else if (uploadResult.isSliceUploadComplete()) { // 上传了一部分
            if (!redisUtil.hHasKey(FileConstant.FILE_UPLOAD_STATUS, param.getMd5())) {
                redisUtil.hset(FileConstant.FILE_UPLOAD_STATUS, param.getMd5(), Boolean.FALSE.toString());
            }
        }
        return FileUploadDTO.builder()
                .chunk(uploadResult.getChunk())
                .sliceUploadComplete(uploadResult.isSliceUploadComplete())
                .uploadComplete(uploadResult.isUploadComplete())
                .path(relativePath)
                .build();
    }

    @Override
    public UploadProgress getUploadProgress(String md5, String name) {
        Object uploadProgressObj = redisUtil.hget(FileConstant.FILE_UPLOAD_STATUS, md5);
        if (uploadProgressObj == null) {
            return UploadProgress.builder().uploadStatus(SliceUploadStatus.FILE_NO_UPLOAD.getValue()).build();
        }
        boolean processing = Boolean.parseBoolean(uploadProgressObj.toString());
        if (processing) {
            return UploadProgress.builder().uploadStatus(SliceUploadStatus.FILE_UPLOADED.getValue()).build();
        } else {
            return LocalUpload.getUploadProgress(getSavePath(md5, name));
        }
    }

    @Override
    public Boolean checkMd5(String md5) {
        Object uploadProgressObj = redisUtil.hget(FileConstant.FILE_UPLOAD_STATUS, md5);
        return uploadProgressObj != null && Boolean.parseBoolean(uploadProgressObj.toString());
    }

    private String getSavePath(String md5, String name) {
        return Paths.get(uploadProperties.getSaveDir(), md5, name).toString();
    }
}